#include "head.h"
#include <iostream>

using std::cout;
using std::endl;

//接收确定的length个字节数的函数
int recvn(int sockfd, void * buff, int length)
{
    int left = length; 
    char * pbuf = (char*)buff;
    int ret = 0;
    while(left > 0) {
        ret = recv(sockfd, pbuf, left, 0);
        pbuf += ret;
        left -= ret;
    }
    return length - left;
}

int readline(int sockfd, void * buff, int max)
{
    int left = max - 1;
    char * pbuff = (char *)buff;
    int ret = 0;
    int total = 0;//一行数据的总长度
    while(left > 0) {
        ret = recv(sockfd, pbuff, left, MSG_PEEK);

        //查找是否包含'\n'
        for(int i = 0; i < ret; ++i) {
            if(pbuff[i] == '\n') {
                //发现了'\n' i+1的字节数是要从内核缓冲区中移走的
                recvn(sockfd, pbuff, i + 1);
                pbuff[i] = '\0';
                total += (i + 1);
                return total;
            }
        }

        //如果没有发现'\n', 就移走内核接收缓冲区中的数据
        recvn(sockfd, pbuff, ret);
        pbuff += ret;
        left -= ret;
        total += ret;
    }
    //退出while循环时，left个字节都没有发现'\n'
    pbuff = (char*)buff;
    pbuff[max - 1] = '\0';
    return max - 1;
}

int main()
{
    //1. 客户端创建套接字
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    ERROR_CHECK(cfd, -1, "socket");
    //2. 连接服务器
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(8000);
    serveraddr.sin_addr.s_addr = inet_addr("192.168.30.129");
    int ret = connect(cfd, 
                      (const struct sockaddr *)&serveraddr,
                      sizeof(serveraddr));
    ERROR_CHECK(ret, -1, "connect");
    cout << "conn has connected.\n";

    char buff[1024] = {0};
    //第一次recv操作，只拷贝了数据，没有移走内核缓冲区中的数据
    ret = recv(cfd, buff, sizeof(buff), MSG_PEEK);
    cout << "recv peek " << ret << " bytes.\n";
    cout << "1 buff:" << buff << endl;

    memset(buff, 0, sizeof(buff));//清空缓冲区中的数据
    //第二次recv操作, 移走内核接收缓冲区中的数据
    ret = recv(cfd, buff, sizeof(buff), 0);
    cout << "2 buff:" << buff << endl;
    
    close(cfd);
    return 0;
}

